package com.mxchip.livestar.original;

import android.content.Context;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.util.Log;


import com.mxchip.livestar.utils.MyLog;

import java.util.concurrent.ArrayBlockingQueue;

/**
 * Created by Administrator on 2016/11/28.
 * 音频播放
 */
public class AudioPlayer {

    private static final String TAG = "AudioPlayer";

    private static final int DEFAULT_STREAM_TYPE = AudioManager.STREAM_MUSIC;
    private static final int DEFAULT_SAMPLE_RATE = 16000;
    private static final int DEFAULT_CHANNEL_CONFIG = AudioFormat.CHANNEL_OUT_MONO;
    private static final int DEFAULT_AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
    private static final int DEFAULT_PLAY_MODE = AudioTrack.MODE_STREAM;

    private boolean mIsPlayStarted = false;
    private int mMinBufferSize = 640;
    private AudioTrack mAudioTrack;
    private int audioLength = 80;
    private ArrayBlockingQueue<byte[]> audioQueue = new ArrayBlockingQueue<>(audioLength);
    private PlayAudioThread mPlayAudioThread;
    private boolean mPlayThreadExitFlag = false;

    private AudioManager audioManager;
    private Context mContext;

    public AudioPlayer(Context context) {
        this.mContext = context;
        audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
    }

    public boolean startPlayer() {
        return startPlayer(DEFAULT_STREAM_TYPE, DEFAULT_SAMPLE_RATE, DEFAULT_CHANNEL_CONFIG, DEFAULT_AUDIO_FORMAT,2);

    }
    public boolean startIDLEPlayer() {
        return startPlayer(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT,8);

    }
    private boolean startPlayer(int streamType, int sampleRateInHz, int channelConfig, int audioFormat,int PrimePlaySize) {
        if (mIsPlayStarted) {
            return false;
        }
        audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
        audioManager.setMode(streamType);
//        audioManager.setSpeakerphoneOn(true);//使用扬声器外放，即使已经插入耳机
        audioManager.setStreamVolume(streamType, (int) (audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC) * 0.3), 0);//设置70%的播放音量
        mMinBufferSize = AudioTrack.getMinBufferSize(sampleRateInHz, channelConfig, audioFormat);
        if (mMinBufferSize == AudioTrack.ERROR_BAD_VALUE) {
            return false;
        }

        mAudioTrack = new AudioTrack(streamType, sampleRateInHz, channelConfig, audioFormat, mMinBufferSize * PrimePlaySize, DEFAULT_PLAY_MODE);
        if (mAudioTrack.getState() == AudioTrack.STATE_UNINITIALIZED) {
            return false;
        }
        try {
            if (mPlayAudioThread == null) {
                mPlayThreadExitFlag = false;
                mPlayAudioThread = new PlayAudioThread();
                mPlayAudioThread.start();
            }
        } catch (Exception e) {
            return false;
        }
        if (audioManager != null) {
            audioManager.setMode(AudioManager.MODE_NORMAL);
        }
        mIsPlayStarted = true;
        return true;
    }

    public int getMinBufferSize() {
        return mMinBufferSize;
    }

    public void stopPlayer() {
        if (!mIsPlayStarted) {
            return;
        }
        if (mPlayAudioThread != null) {
            mPlayThreadExitFlag = true;
//            mPlayAudioThread.interrupt();
            mPlayAudioThread = null;
        }
        audioQueue.clear();
        if (mAudioTrack != null && mAudioTrack.getState() != AudioTrack.STATE_UNINITIALIZED) {
            if (mAudioTrack.getPlayState() != AudioTrack.PLAYSTATE_STOPPED) {
                try {
                    mAudioTrack.stop();
                } catch (IllegalStateException e) {
                    mAudioTrack.release();
                    e.printStackTrace();
                }
            }
            mAudioTrack.release();
            mAudioTrack = null;
            mIsPlayStarted = false;
        }

        mContext = null;
    }


    /*
     *  音频播放线程
     */
    class PlayAudioThread extends Thread {
        private final Object SYNC = new Object();

        public void notifyNewDataArrive() {
            synchronized (SYNC) {
                SYNC.notify();
            }
        }

        @Override
        public void run() {
            if (mAudioTrack == null)
                return;
            try {
                android.os.Process.setThreadPriority(
                        android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
            } catch (Exception e) {
                Log.d(TAG, "Set play thread priority failed: " + e.getMessage());
            }
            try {
                mAudioTrack.play();
            } catch (Exception e) {
                e.printStackTrace();
            }
            while (!mPlayThreadExitFlag) {
                try {
//                    if (SystemData.getInstance().getCurrentState() == com.videohigh.hxb3288a.base.statemachine.stateandevent.State.OFFLINE
//                    ||SystemData.getInstance().getCurrentState() == com.videohigh.hxb3288a.base.statemachine.stateandevent.State.IDLE){
//                         byte[] mData = new byte[1920];
//                        int size = ScreenPushNative.GetAudioFrame(mData);
//                        addAudioData(mData);
//                    }
                    byte[] data = audioQueue.poll();
                    if (null != data) {
                        mAudioTrack.write(data, 0, data.length);
                    } else {
                        synchronized (SYNC) {
                            SYNC.wait();
                        }
                    }
                } catch (Exception e) {
                    break;
                }
            }
        }
    }
    public int addAudioData(byte[] data) {
        if (audioQueue.size() >= audioLength) {
            audioQueue.poll();
        }
        if (audioQueue != null)
            audioQueue.add(data);
        MyLog.logD( MyLog.AUDIO_PLAYER_MODEL,"AudioPlayer::"+"addAudioData: "+audioQueue.size());

        if (mPlayAudioThread != null) {
            mPlayAudioThread.notifyNewDataArrive();
        }
        return audioQueue == null ? 0 : audioQueue.size();
    }

    public void clearAudioqueue() {
        if (audioQueue != null) {
            audioQueue.clear();
        }
    }

    public void setMicrophone(boolean open) {
        if (open) {
            audioManager.setMicrophoneMute(open);
        } else {
            audioManager.setMicrophoneMute(open);
        }
    }

    public AudioManager getAudioManager() {
        return audioManager;
    }
}
